/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
 * Description: The IR operator register
 */
#ifndef _DOMI_OP_OPERATOR_FACTORY_H_
#define _DOMI_OP_OPERATOR_FACTORY_H_

#include <memory>
#include <string>
#include <functional>
#include "infra/base/securestl.h"
#include "graph/operator.h"

namespace hiai {
/*
 * @brief 用于创建Operator
 */
class OperatorFactory {
public:
    /*
     * @ingroup graph
     * @brief 返回OperatorFactory实例
     * @return OperatorFactory对象
     */
    static OperatorFactory* Instance();

    /*
     * @ingroup graph
     * @brief 根据输入的op type和op name，创建Operator
     * @param [in] opType Op类型, op name
     * @return 创建出的Operator
     */
    std::shared_ptr<ge::Operator> CreateOperator(const std::string& opType, const std::string& name); // lint !e148

    // Factory实例由shared_ptr自动释放，shared_ptr内部会间接调用析构函数，析构函数如果不公开会产生编译错误。
    // 另外的解决方法是为shared_ptr指定deleter，然后将deleter设置为当前类的友元，但这种方法实现较复杂。
    ~OperatorFactory() {};

protected:
    /*
     * @brief Operator的创建函数
     * @return 创建出的Operator
     */
    using CREATOR_FUN = std::function<std::shared_ptr<ge::Operator>(std::string)>;

    /*
     * @ingroup graph
     * @brief 工厂实例只能自动创建，不能通过new的方式创建，所以构造函数不对外公开
     */
    OperatorFactory()
    {
    }

    /*
     * @ingroup graph
     * @brief 注册创建函数
     * @param [in] type Op类型
     * @param [in] fun Operator的创建函数
     */
    void RegisterCreator(const std::string& type, CREATOR_FUN fun);

private:
    /*
     * @ingroup graph
     * @brief 每个Op对应一个Creator函数
     */
    std::map<std::string, CREATOR_FUN> creatorMap_ {}; // lint !e1073

    friend class OperatorRegisterar;
};

/*
 * @ingroup graph
 * @brief 用于为不同类型的Op注册Creator函数
 *
 */
class OperatorRegisterar {
public:
    /*
     * @ingroup graph
     * @brief 构造函数
     * @param [in] framework    Framework类型
     * @param [in] opType      Op类型
     * @param [in] fun          Op对应的Creator函数
     */
    OperatorRegisterar(const std::string& opType, OperatorFactory::CREATOR_FUN fun)
    {
        OperatorFactory::Instance()->RegisterCreator(opType, fun);
    }
    ~OperatorRegisterar()
    {
    }
};

/*
 * @ingroup graph
 * @brief OpCreator的注册宏
 * @param [in] framework    Framework类型
 * @param [in] opType      Op类型
 * @param [in] clazz       Operator的实现类
 */
#define REGISTER_OPERATOR_CREATOR(opType, clazz) \
    std::shared_ptr<ge::Operator> Creator_##opType##_Operator_Creator(std::string name) \
    { \
        std::shared_ptr<clazz> ptr = hiai::make_shared_nothrow<clazz>(name); \
        return std::shared_ptr<ge::Operator>(ptr); \
    } \
    static OperatorRegisterar g_##opType##_Operator_Creator(#opType, Creator_##opType##_Operator_Creator)
} // namespace hiai

#endif
